package hello

import (
	"appengine"
	"appengine/blobstore"
	"net/http"
	"html/template"
	"strconv"
	"reflect"
)

var tmplFuncs = template.FuncMap{"unitName": unitName, "eq": reflect.DeepEqual, "raw": raw, 
	"printCount": printCount, "formatTime": formatTime, "bytesToString": bytesToString,
	"recipeMetaDescription": recipeMetaDescription, "substr": substr}

var adminTemplates = template.Must(template.New("test").Funcs(tmplFuncs).ParseFiles(
	"admin/header.html", "admin/index.html", "admin/products.html", 
	"admin/editProduct.html", "admin/recipes.html", "admin/editRecipe.html", 
	"admin/categories.html", "admin/editCategory.html"))
	
var templates = template.Must(template.New("test").Funcs(tmplFuncs).ParseFiles(
	"application/header.html", "application/index.html", "application/recipes.html",
	"application/addRecipeForm.html", "application/meta.html", "application/footer.html", 
	"application/recipe.html", "admin/login.html"))

func init() {
	// application handlers
    http.HandleFunc("/", makeHandler(actionRoot))
    http.HandleFunc("/recipes", makeHandler(actionRecipes))
    http.HandleFunc("/recipe", makeHandler(actionRecipe))
    http.HandleFunc("/addRecipeForm", makeHandler(actionAddRecipeForm))
    http.HandleFunc("/addRecipeComment", makeHandler(actionAddRecipeComment))
    // static handler
    pfx := "/public/"
    staticHandler := http.StripPrefix(pfx, http.FileServer(http.Dir("public")))
    http.Handle(pfx, staticHandler)
    // root files static handler
    fileHandler := http.FileServer(http.Dir("."))
    http.Handle("/robots.txt", fileHandler)
    http.HandleFunc("/sitemap.xml", makeHandler(siteMapHandler))
    http.Handle("/yandex_583cc5f61f287bbf.html", fileHandler)
	// blob handler
    http.HandleFunc("/file", makeHandler(actionGetBlob))
	// login handlers    
    http.HandleFunc("/loginForm", makeHandler(actionLoginForm))
    http.HandleFunc("/login", actionLogin)
    // admin handlers
    // admin product
    http.HandleFunc("/admin", makeAdminHandler(actionAdminRoot))
    http.HandleFunc("/admin/createTestObjects", makeAdminHandler(actionAdminCreateTestObjects))
    http.HandleFunc("/admin/products", makeAdminHandler(actionAdminProducts))
    http.HandleFunc("/admin/addProductForm", makeAdminHandler(actionAdminAddProductForm))
    http.HandleFunc("/admin/addProduct", makeAdminHandler(actionAdminAddProduct))
    http.HandleFunc("/admin/editProductForm", makeAdminHandler(actionAdminEditProductForm))
    http.HandleFunc("/admin/updateProduct", makeAdminHandler(actionAdminUpdateProduct))
    http.HandleFunc("/admin/deleteProduct", makeAdminHandler(actionAdminDeleteProduct))
	// admin recipe & ingredient
    http.HandleFunc("/admin/recipes", makeAdminHandler(actionAdminRecipes))
    http.HandleFunc("/admin/addRecipeForm", makeAdminHandler(actionAdminAddRecipeForm))
    http.HandleFunc("/admin/addRecipe", makeAdminHandler(actionAdminAddRecipe))
    http.HandleFunc("/admin/editRecipeForm", makeAdminHandler(actionAdminEditRecipeForm))
    http.HandleFunc("/admin/updateRecipe", makeAdminHandler(actionAdminUpdateRecipe))
    http.HandleFunc("/admin/deleteRecipe", makeAdminHandler(actionAdminDeleteRecipe))
    http.HandleFunc("/admin/addIngredient", makeAdminHandler(actionAdminAddIngredient))
    http.HandleFunc("/admin/deleteIngredient", makeAdminHandler(actionAdminDeleteIngredient))
    http.HandleFunc("/admin/deleteRecipeComment", makeAdminHandler(actionAdminDeleteRecipeComment))
    http.HandleFunc("/admin/addRecipeComment", makeAdminHandler(actionAdminAddRecipeComment))
    http.HandleFunc("/admin/categories", makeAdminHandler(actionAdminCategories))
    http.HandleFunc("/admin/addCategory", makeAdminHandler(actionAdminAddCategory))
    http.HandleFunc("/admin/deleteCategory", makeAdminHandler(actionAdminDeleteCategory))
    http.HandleFunc("/admin/editCategoryForm", makeAdminHandler(actionAdminEditCategoryForm))
    http.HandleFunc("/admin/updateCategory", makeAdminHandler(actionAdminUpdateCategory))
}

func actionAdminRoot(c *appengine.Context, w http.ResponseWriter, r *http.Request) {
	err := adminTemplates.ExecuteTemplate(w, "index.html", nil)
	panicIfErr(err)
}

func actionLoginForm(c *appengine.Context, w http.ResponseWriter, r *http.Request, params Params) (tmpl string) {
	tmpl = "login.html"
	return
}

func actionLogin(w http.ResponseWriter, r *http.Request) {
	login := r.FormValue("login")
	password := r.FormValue("password")
	if login == "admin" && password == "ekk6vy36" {
		val := hashString(login + password)
		c := appengine.NewContext(r)
		saveAuthCookie(&c, val)
		http.SetCookie(w, &http.Cookie{Name:loggedInSessAttr, Value: val})
		http.Redirect(w, r, "/admin", http.StatusFound)
	} else {
		println("AUTHENTICATION FAILED")
		http.Redirect(w, r, "/loginForm", http.StatusFound)
	}
}

func actionGetBlob(c *appengine.Context, w http.ResponseWriter, r *http.Request, params Params) (tmpl string) {
	blobstore.Send(w, appengine.BlobKey(r.FormValue("key")))
	return
}

func actionAdminCreateTestObjects(c *appengine.Context, w http.ResponseWriter, r *http.Request) {
	for i := int64(1); i < 15; i++ {
		saveProduct(c, &Product{Name: "Product #" + strconv.FormatInt(i, 10)})
		saveRecipe(c, &Recipe{Name: "Recipe #" + strconv.FormatInt(i, 10), Code: "", Display: true})
	}
}